package com.test;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.parser.lexparser.LexicalizedParser;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.AnnotationPipeline;
import edu.stanford.nlp.pipeline.POSTaggerAnnotator;
import edu.stanford.nlp.pipeline.TokenizerAnnotator;
import edu.stanford.nlp.pipeline.WordsToSentencesAnnotator;
import edu.stanford.nlp.time.SUTime.Temporal;
import edu.stanford.nlp.time.TimeAnnotations;
import edu.stanford.nlp.time.TimeAnnotator;
import edu.stanford.nlp.time.TimeExpression;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeGraphNode;
import edu.stanford.nlp.util.CoreMap;

public class Main {

	private static final String DAY_MONTH = "\\b([1][3-9]|[2][0-9]|3[01])[\\/-](0?[1-9]|1[0-2])([\\/-][0-9]{4})\\b";
	private static final String SINGLE_DIGIT_DAY = "\\b(\\d{4}[\\/-]\\d[\\/-]\\d{2})\\b|\\b(\\d{4}[\\/-]\\d{2}[\\/-]\\d)\\b|\\b(\\d{4}[\\/-]\\d[\\/-]\\d)\\b|\\b(\\d[\\/-]\\d{2}[\\/-]\\d{4})\\b|\\b(\\d{2}[\\/-]\\d[\\/-]\\d{4})\\b|\\b(\\d[\\/-]\\d[\\/-]\\d{4})\\b";

	public static void main(String[] args) {

		// output
		ArrayList<String> dateText = new ArrayList<String>();
		ArrayList<Calendar> dates = new ArrayList<Calendar>();
		Calendar start = Calendar.getInstance();
		Calendar end = Calendar.getInstance();
		ArrayList<String> phrases = new ArrayList<String>();
		ArrayList<String> titles = new ArrayList<String>();
		ArrayList<String> locations = new ArrayList<String>();
		// **************************************************************************

		// model
		Properties props = new Properties();
		AnnotationPipeline pipeline = new AnnotationPipeline();
		pipeline.addAnnotator(new TokenizerAnnotator(false));
		pipeline.addAnnotator(new WordsToSentencesAnnotator(false));
		pipeline.addAnnotator(new POSTaggerAnnotator(false));
		pipeline.addAnnotator(new TimeAnnotator("sutime", props));

		String parserModel = "edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz";
		LexicalizedParser lp = LexicalizedParser.loadModel(parserModel);
		// **************************************************************************

		System.out.println("\n******************************************\n");

		String input = "the seminar is held at room 2306";

		String[] lines = input.split("\n");

		for (String line : lines) {

			Pattern p = Pattern.compile(DAY_MONTH);
			Matcher m = p.matcher(line);

			while (m.find()) {
				String oldPart = line.substring(m.start(), m.end());
				String[] tmp = oldPart.split("[\\/-]");
				if (tmp[0].length() == 1) {
					tmp[0] = "0" + tmp[0];
				}
				if (tmp[1].length() == 1) {
					tmp[1] = "0" + tmp[1];
				}
				String newPart = tmp[1] + "-" + tmp[0] + "-" + tmp[2];
				line = line.replace(oldPart, newPart);
			}

			p = Pattern.compile(SINGLE_DIGIT_DAY);
			m = p.matcher(line);
			
			while (m.find()) {
				String oldPart = line.substring(m.start(), m.end());
				String[] tmp = oldPart.split("[\\/-]");
				if (tmp[0].length() == 1) {
					tmp[0] = "0" + tmp[0];
				}
				if (tmp[1].length() == 1) {
					tmp[1] = "0" + tmp[1];
				}
				if (tmp[2].length() == 1) {
					tmp[2] = "0" + tmp[2];
				}
				String newPart = tmp[0] + "-" + tmp[1] + "-" + tmp[2];
				line = line.replace(oldPart, newPart);
			}

			Annotation annotation = new Annotation(line);

			Calendar today = Calendar.getInstance();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String todayFormatted = formatter.format(today.getTime());

			annotation.set(CoreAnnotations.DocDateAnnotation.class,
					todayFormatted);
			pipeline.annotate(annotation);

			List<CoreMap> timexAnnsAll = annotation
					.get(TimeAnnotations.TimexAnnotations.class);

			System.out.println("input string: " + line + "\n");
			for (CoreMap cm : timexAnnsAll) {
				// List<CoreLabel> tokens = cm
				// .get(CoreAnnotations.TokensAnnotation.class);

				Temporal temporal = cm.get(TimeExpression.Annotation.class)
						.getTemporal();

				Calendar date = Calendar.getInstance();
				date.set(Calendar.MINUTE, 0);
				date.set(Calendar.SECOND, 0);
				String temporalStirng = temporal.toString();
				String temporalType = temporal.getTimexType().toString();
				String temporalDay = null;
				String temporalTime = null;

				if (temporalType.equals("TIME")) {

					String[] dayTimeArray = temporalStirng.split("T");
					if (dayTimeArray == null || dayTimeArray.length < 2) {
						continue;
					}
					temporalDay = dayTimeArray[0];
					temporalTime = dayTimeArray[1];

					String[] dayArray = temporalDay.split("-");
					if (dayArray == null) {
						continue;
					}
					int length = dayArray.length;

					if (length == 1) {

						if (isInteger(dayArray[0])) {
							date.set(Calendar.YEAR,
									Integer.parseInt(dayArray[0]));
						}
					} else if (length == 2) {

						if (isInteger(dayArray[0]) && isInteger(dayArray[1])) {
							date.set(Calendar.YEAR,
									Integer.parseInt(dayArray[0]));
							date.set(Calendar.MONTH,
									Integer.parseInt(dayArray[1]) - 1);
						}
					} else if (length >= 3) {

						if (isInteger(dayArray[0]) && isInteger(dayArray[1])
								&& isInteger(dayArray[2])) {
							date.set(Calendar.YEAR,
									Integer.parseInt(dayArray[0]));
							date.set(Calendar.MONTH,
									Integer.parseInt(dayArray[1]) - 1);
							date.set(Calendar.DAY_OF_MONTH,
									Integer.parseInt(dayArray[2]));
						}
					} else {
						continue;
					}

					String[] timeArray = temporalTime.split(":");
					if (timeArray == null || timeArray.length < 2) {
						continue;
					}
					if (isInteger(timeArray[0]) && isInteger(timeArray[1])) {

						date.set(Calendar.HOUR_OF_DAY,
								Integer.parseInt(timeArray[0]));
						date.set(Calendar.MINUTE,
								Integer.parseInt(timeArray[1]));

						String tmp = cm.toString();
						dateText.add(temporal.toString());
						dates.add(date);
						line = line.replace(tmp, "");
					}

				} else if (temporalType.equals("DATE")) {

					if (temporalStirng != null && temporalStirng.length() >= 10) {

						temporalDay = temporalStirng.substring(0, 10);
						String[] dayTimeArray = temporalDay.split("-");

						if (dayTimeArray != null && dayTimeArray.length >= 3) {
							date.set(Calendar.YEAR,
									Integer.parseInt(dayTimeArray[0]));
							date.set(Calendar.MONTH,
									Integer.parseInt(dayTimeArray[1]) - 1);
							date.set(Calendar.DAY_OF_MONTH,
									Integer.parseInt(dayTimeArray[2]));
						}
						String tmp = cm.toString();
						dateText.add(temporal.toString());
						dates.add(date);
						line = line.replace(tmp, "");
					}
				}
			}

			// line = line.replace("-", " ");
			Tree parse = lp.parse(line);

			System.out.println("Tree: ");
			parse.pennPrint();
			System.out.println();

			for (Tree subtree : parse) {

				if (subtree.value().equals("VP")) {
					for (Tree child : subtree.children()) {
						if (child.value().equals("NP")
								|| child.value().equals("NN")) {

							List<Tree> leaves = subtree.getLeaves();
							String phrase = "";
							for (Tree leaf : leaves) {
								phrase = phrase + leaf.value() + " ";
							}
							phrase = phrase.replaceAll("-LRB- ", "(");
							phrase = phrase.replaceAll(" -RRB-", ")");
							phrase = phrase.trim();
							if (phrase.endsWith(":")) {
								phrase = phrase.substring(0,
										phrase.length() - 1);
							}
							phrases.add(phrase.trim());
							break;
						}
					}
				}

				if (subtree.value().equals("PP")) {
					for (Tree child : subtree.children()) {
						if (child.value().equals("NP")) {

							List<Tree> leaves = child.getLeaves();
							String location = "";
							for (Tree leaf : leaves) {
								location = location + leaf.value() + " ";
							}
							location = location.replaceAll("-LRB- ", "(");
							location = location.replaceAll(" -RRB-", ")");
							location = location.trim();
							if (location.endsWith(":")) {
								location = location.substring(0,
										location.length() - 1);
							}
							locations.add(location.trim());
						}
					}
				}

				if (subtree.value().equals("NP")) {

					boolean allNp = true;
					boolean nn = false;
					boolean np = false;
					boolean nnpAndCd = false;

					Tree[] children = subtree.children();

					for (int i = 0; i < children.length; i++) {

						String value = children[i].value();

						if (children.length == 2 && i + 1 < children.length
								&& value.equals("NNP")
								&& children[i + 1].value().equals("CD")) {
							nnpAndCd = true;
						}

						// if (value.equals("CD")) {
						// String location = children[i].getChild(0).value();
						// if (checkCJK(location)) {
						//
						// location = location.replaceAll("-LRB- ", "(");
						// location = location.replaceAll(" -RRB-", ")");
						// location = location.trim();
						// if (location.endsWith(":")) {
						// location = location.substring(0,
						// location.length() - 1);
						// }
						// locations.add(location.trim());
						// }
						// }

						switch (value) {

						case ",":
							break;

						case "NP":
							np = true;
							break;

						case "CD":
							allNp = false;
							break;

						case "NN":
							nn = true;
							allNp = false;
							break;

						default:
							allNp = false;
							break;
						}

					}
					if (allNp || nnpAndCd) {

						List<Tree> leaves = subtree.getLeaves();
						String location = "";
						for (Tree leaf : leaves) {
							location = location + leaf.value() + " ";
						}
						location = location.replaceAll("-LRB- ", "(");
						location = location.replaceAll(" -RRB-", ")");
						location = location.trim();
						if (location.endsWith(":")) {
							location = location.substring(0,
									location.length() - 1);
						}
						locations.add(location.trim());

					} else if (nn || np) {

						List<Tree> leaves = subtree.getLeaves();
						String phrase = "";
						for (Tree leaf : leaves) {
							phrase = phrase + leaf.value() + " ";
						}
						phrase = phrase.replaceAll("-LRB- ", "(");
						phrase = phrase.replaceAll(" -RRB-", ")");
						phrase = phrase.trim();
						if (phrase.endsWith(":")) {
							phrase = phrase.substring(0, phrase.length() - 1);
						}
						phrases.add(phrase.trim());

					}
				}
			}
		}

		System.out.println("\ndate and time: ");
		for (int i = 0; i < dates.size(); i++) {
			System.out.println(dateText.get(i) + " --> "
					+ dates.get(i).getTime() + "\n");
		}

		if (phrases != null && phrases.size() > 0) {
			titles.add(phrases.get(0));
		}
		System.out.println("\ntitle: ");
		for (String title : titles) {
			System.out.println(title);
		}

		System.out.println("\nlocation: ");
		for (String location : locations) {
			System.out.println(location);
		}

		System.out.println("\nphrases: ");
		for (String phrase : phrases) {
			System.out.println(phrase);
		}

	}

	public static boolean isInteger(String input) {
		try {
			Integer.parseInt(input);
		} catch (NumberFormatException e) {
			return false;
		} catch (NullPointerException e) {
			return false;
		}
		return true;
	}

}
